package com.liveinstars.im.util;

import com.onepiece.shipelves.common.acframework.trie.Emit;
import com.onepiece.shipelves.common.acframework.trie.Trie;
import com.onepiece.shipelves.common.utils.JsonUtil;
import com.liveinstars.api.im.vo.WordBadLevel;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;

/**
 *
 */
public class BadWordUtil {

    private static Trie eroticismTrie = null;
    private static Trie reactionTrie = null;
    private static Trie otherTrie = null;
    public static Trie allTrie = null;
    private static final Logger LOGGER = LoggerFactory.getLogger(BadWordUtil.class);

    public static void initBadWordTree(String eroticism, String reaction, String other) {
        LOGGER.info("initBadWordTree {} {} {}", eroticism.length(), reaction.length(), other.length());
        if(allTrie == null && !StringUtils.isEmpty(eroticism)) {
            eroticismTrie = new Trie(false);
            Arrays.stream(eroticism.split("\n")).forEach(s -> {
                if (!StringUtils.isEmpty(s)) {
//                    LOGGER.info("addKeyword {}", s);
                    eroticismTrie.addKeyword(s);
                }
            });
            reactionTrie = new Trie(false);
            Arrays.stream(reaction.split("\n")).forEach(s -> {
                if (!StringUtils.isEmpty(s)) {
                    reactionTrie.addKeyword(s);
                }
            });
            otherTrie = new Trie(false);
            Arrays.stream(other.split("\n")).forEach(s -> {
                if (!StringUtils.isEmpty(s)) {
                    otherTrie.addKeyword(s);
                }
            });
            StringBuilder stringBuilder = new StringBuilder(eroticism);
            stringBuilder.append(reaction).append(other);
            allTrie = new Trie(false);

            Arrays.stream(stringBuilder.toString().split("\n")).forEach(s -> {
                if (!StringUtils.isEmpty(s)) {
                    allTrie.addKeyword(s);
                }
            });
        }
        LOGGER.info("initBadWordTree end {}", allTrie != null);
    }



//    public static String transferToHealth(String content) {
//
//        if(eroticismTrie == null){
//            return content;
//        }
//        Collection<Emit> emits = null;
//        emits = getBadWordTree().parseText(content);
//        int start = 0;
//        StringBuilder stringBuilder = new StringBuilder();
//        for (Emit emit : emits) {
//            int emitStart = emit.getStart();
//            int emitEnd = emit.getEnd();
//            if(emitStart >= start) {
//                stringBuilder.append(content.substring(start, emitStart)).append("***");
//            }else {
//
//            }
//            start = emitEnd + 1;
//        }
//        stringBuilder.append(content.substring(start, content.length()));
//        return stringBuilder.toString();
//    }

    public static WordBadLevel getWordBadLevel(String content, boolean needShadow){

        LOGGER.info("getWordBadLevel {}", eroticismTrie != null);
        if(eroticismTrie == null || reactionTrie == null || otherTrie == null){
            return new WordBadLevel(false);
        }
        WordBadLevel wordBadLevel = new WordBadLevel(true);
        List<String> eroticismBadWords = new ArrayList<>();
        List<String> eroticismBadWordsLocation = new ArrayList<>();
        List<String> reactionBadWords = new ArrayList<>();
        List<String> reactionBadWordsLocation = new ArrayList<>();
        List<String> otherBadWords = new ArrayList<>();
        List<String> otherBadWordsLocation = new ArrayList<>();

        int eroticismSize = doBadWordMatch(eroticismTrie, content, eroticismBadWords, eroticismBadWordsLocation);
        int reactionSize = doBadWordMatch(reactionTrie, content, reactionBadWords, reactionBadWordsLocation);
        int otherSize = doBadWordMatch(otherTrie, content, otherBadWords, otherBadWordsLocation);

        wordBadLevel.setEroticismBadWords(eroticismBadWords);
        wordBadLevel.setEroticismBadWordsLocation(eroticismBadWordsLocation);
        wordBadLevel.setReactionBadWords(reactionBadWords);
        wordBadLevel.setReactionBadWordsLocation(reactionBadWordsLocation);
        wordBadLevel.setOtherBadWords(otherBadWords);
        wordBadLevel.setOtherBadWordsLocation(otherBadWordsLocation);

        wordBadLevel.setMatchNum(eroticismSize + reactionSize + otherSize);
        wordBadLevel.setScore(getScore(eroticismSize, reactionSize, otherSize));


        if(needShadow && allTrie != null) {
            wordBadLevel.setShadowContent(getShadowContent(content));
        }
        LOGGER.info("getWordBadLevel end {}", JsonUtil.toJson(wordBadLevel));
        return wordBadLevel;
    }

    private static int doBadWordMatch(Trie trie, String content, List<String> badWords, List<String> badWordsLocation) {
        Collection<Emit> emits = null;
        emits = trie.parseText(content);
        int start = 0;
        LOGGER.info("doBadWordMatch {} {} {}", content, emits.size(), trie != null);
        for (Emit emit : emits) {
            int emitStart = emit.getStart();
            int emitEnd = emit.getEnd();
            if(emitStart >= start) {
                badWords.add(content.substring(emitStart, emitEnd + 1));
                badWordsLocation.add(emitStart + ":" + emitEnd);
            }else {

            }
            start = emitEnd + 1;
        }
        return emits.size();
    }

    private static int getScore(int eroticismSize, int reactionSize, int otherSize) {
        int score = eroticismSize * 2 + reactionSize * 20 + otherSize * 1;
        return score > 100 ? 100 : score;
    }


    public static void refreshTree(String eroticism, String reaction, String other) {
        allTrie = null;
        initBadWordTree(eroticism, reaction, other);
    }

    public static String transferToHealth(String content) {
        if(allTrie == null){
            return content;
        }
        return getShadowContent(content);
    }

    private static String getShadowContent(String content) {
        StringBuilder stringBuilder = new StringBuilder();
        Collection<Emit> emits = null;
        emits = allTrie.parseText(content);
        int start = 0;

        for (Emit emit : emits) {
            int emitStart = emit.getStart();
            int emitEnd = emit.getEnd();
            if(emitStart >= start) {
                stringBuilder.append(content.substring(start, emitStart)).append("***");
            }else {

            }
            start = emitEnd + 1;
        }

        stringBuilder.append(content.substring(start, content.length()));
        return stringBuilder.toString();
    }
}
